#include <termios.h>
#include <fcntl.h>
#include <stdio.h>
#include <unistd.h>
#include <string.h>
#include <errno.h>

main(){
	
	int pid, serial_fd, strlength, arg = 0; //process ID info for forking and file descriptor for serial stream -go
	struct termios scorbot_config; //sets up termios configuration structure for the scorbot serial port -go
	char c; //charater for printing from serial port -go
	char input[10];
	char io[1];
	
	const char *device = "/dev/ttyUSB0"; //sets where the serial port is plugged in -go
	serial_fd = open(device, O_RDWR | O_NOCTTY); //opens serial port in device slot -go
	if(serial_fd == -1) {
		fprintf(stdout, "failed to open serial port\n");
		return 1;
	}
	
	//tcgetattr(serial_fd, &scorbot_config);
	
	//cfsetispeed(&scorbot_config, B9600); //set baud input to 9600
	//cfsetospeed(&scorbot_config, B9600); //set baud output to 9600
	bzero(&scorbot_config, sizeof(scorbot_config)); /* clear struct for new port settings */
	
	
	/* 
	  BAUDRATE: Set bps rate. You could also use cfsetispeed and cfsetospeed.
	  //CRTSCTS : output hardware flow control (only used if the cable has
	  //          all necessary lines. See sect. 7 of Serial-HOWTO)
	  CS8     : 8n1 (8bit,no parity,1 stopbit)
	  CLOCAL  : local connection, no modem contol
	  CREAD   : enable receiving characters
	*/
	 scorbot_config.c_cflag = B9600 | CS8 | CLOCAL | CREAD;
	 
	/*
	  IGNPAR  : ignore bytes with parity errors
	  ICRNL   : map CR to NL (otherwise a CR input on the other computer
		        will not terminate input)
	  IGNCR   : ignore carriage returns
	  otherwise make device raw (no other input processing)
	*/
	 scorbot_config.c_iflag = IGNPAR | ICRNL | IGNCR ;//| IXON | IXOFF;
	 
	/*
	 Raw output.
	*/
	 scorbot_config.c_oflag = 0;
	 
	/*
	  ICANON  : enable canonical input
	  disable all echo functionality, and don't send signals to calling program
	*/
	 scorbot_config.c_lflag = ICANON;
	 
	/* 
	  initialize all control characters 
	  default values can be found in /usr/include/termios.h, and are given
	  in the comments, but we don't need them here
	*/
	 scorbot_config.c_cc[VINTR]    = 0;     /* Ctrl-c */ 
	 scorbot_config.c_cc[VQUIT]    = 0;     /* Ctrl-\ */
	 scorbot_config.c_cc[VERASE]   = 0;     /* del */
	 scorbot_config.c_cc[VKILL]    = 0;     /* @ */
	 scorbot_config.c_cc[VEOF]     = 4;     /* Ctrl-d */
	 scorbot_config.c_cc[VTIME]    = 0;     /* inter-character timer unused */
	 scorbot_config.c_cc[VMIN]     = 1;     /* blocking read until 1 character arrives */
	 scorbot_config.c_cc[VSWTC]    = 0;     /* '\0' */
	 scorbot_config.c_cc[VSTART]   = 0;     /* Ctrl-q */ 
	 scorbot_config.c_cc[VSTOP]    = 0;     /* Ctrl-s */
	 scorbot_config.c_cc[VSUSP]    = 0;     /* Ctrl-z */
	 scorbot_config.c_cc[VEOL]     = 0;     /* '\0' */
	 scorbot_config.c_cc[VREPRINT] = 0;     /* Ctrl-r */
	 scorbot_config.c_cc[VDISCARD] = 0;     /* Ctrl-u */
	 scorbot_config.c_cc[VWERASE]  = 0;     /* Ctrl-w */
	 scorbot_config.c_cc[VLNEXT]   = 0;     /* Ctrl-v */
	 scorbot_config.c_cc[VEOL2]    = 0;     /* '\0' */

	/* 
	  now clean the modem line and activate the settings for the port
	*/
	 tcflush(serial_fd, TCIOFLUSH);
	 tcsetattr(serial_fd,TCSANOW,&scorbot_config);

	
	pid = fork(); //splits process for recieving and sending -go
	
	if(pid == 0){ //child process continually receives -go
		fprintf(stdout, "Receiving Process Started\n"); //-debug -go
		while(1){
			if (read(serial_fd, &c, 1)>0){ //if there's something from the serial port -go
				fprintf(stdout, "%c", c);
			}
		}
	}
	else{ //parent process sends input on return -go
		fprintf(stdout, "Sending Process Started\n"); //-debug -go
		while(1){
			bzero(input, 10);
			//read(0, input, 10);
			do {
				scanf("%c", io);
				input[arg] = *io;
				arg++;
			}while(*io != '\n');
			input[arg-1] = '\r';
			input[arg] = '\0';
			//scanf("%s", input);
			strlength = strlen(input);
			//input[strlength] = '\r';
			write(serial_fd, input, strlen(input));
			fprintf(stdout, "%s\n", input);
			arg = 0;
		}
	}

	
	close(serial_fd); //close serial stream -go
	
	fprintf(stdout, "complete"); //-debug -go

return 0;
}
